-----------------------------
--------Module Name : decode_driver
--------Module Function : Receive BUS1553 Data and Send to HV5812



library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

entity decode_driver is
port(
		Clock		: in std_logic;						------- Clock, 8MHz, the same as the decode_1553
		
		rx_data	: in std_logic_vector(0 to 15);	------- rx_data, output by decode_1553
		rx_valid	: in std_logic;						------- rx_valid, output by decode_1553
		rx_csw	: in std_logic;						------- rx_csw, output by decode_1553, indicates command and status word
		rx_dw		: in std_logic;						------- rx_dw, output by decode_1553, indicates data word
		rx_perr	: in std_logic;						------- rx_perr, output by decode_1553, indicates error received.
		
		E_LED		: out std_logic;						------- E_LED, light up when received error
		
		HV_Strobe	: out std_logic;					------- HV_Strobe, Latch data to HV5812 register by rising_edge
		HV_BLK		: out std_logic;					------- HV_BLK, Blank HV5812 output when pull high.
		HV_DOUT		: out std_logic;					------- HV_DOUT, Serial data to HV5812.
		HV_CLK		: out std_logic					------- HV_CLK, Serial Clock to HV5812.
);
end entity;

architecture fun of decode_driver is

signal err_data	: std_logic_vector(15 downto 0);
signal data_status	: std_logic_vector(2 downto 0);
signal rx_data_buf	: std_logic_vector(0 to 16);

signal data_type		: std_logic;

signal State		: std_logic_vector(3 downto 0);
signal index		: integer range 0 to 19;
signal delay_cnt	: integer range 0 to 255;
signal empty_cnt	: integer range 0 to 5;

begin
	data_type <= rx_csw and not rx_dw;
	process(Clock)
		begin
			if Clock 'event and Clock = '1' then
				case State is
					when "0000" =>					
						if rx_valid = '1' then
							case rx_perr is
								when '1' =>
									err_data <= rx_data;
									E_LED	<= '1';							--light up when received error
									State <= "0000";
								when '0' =>
									E_LED	<= '0';
									rx_data_buf(1 to 16) <= rx_data; --receive data 
									if data_type = '1' then
										data_status <= "101";
									else
										data_status <= "010";
									end if;
									State <= "0001";
							end case;
						end if;
					when "0001" =>
						HV_Strobe <= '0';							-- Pull low for Rising edge
						HV_BLK <= '1';								-- Blank output
						HV_CLK <= '0';
						HV_DOUT <= '0';
						delay_cnt <= 0;
						index <= 16;
						empty_cnt <= 0;							-- 16 bit output are used from 20 bit total, empty_cnt represent dummy bits.
						State <= "0010";
					when "0010" =>
						if empty_cnt = 2 then					-- 2 bit dummy bit (20, 19) transmit first
							State <= "0101";
						else
							HV_DOUT <= '0';						-- serial data set up.
							empty_cnt <= empty_cnt + 1;
							State <= "0011";
						end if;			
							
					when "0011" =>
						HV_CLK <= '1';								-- positive edge Clock
						if delay_cnt = 1 then
							State <= "0100";
						else
							delay_cnt <= delay_cnt + 1;		-- positive width is not less than 150ns by data sheet.
						end if;
						
					when "0100" =>				
						HV_CLK <= '0';								-- negative edge Clock
						State <= "0010";
						
					when "0101" =>
						delay_cnt <= 0;
						if index = 8 then							-- bit 9 -16 ([8:15])
							empty_cnt <= 0;
							State <= "1000";
						else
							index <= index - 1;
							HV_DOUT <= rx_data_buf(index);
							State <= "0110";
						end if;
					when "0110" =>
						HV_CLK <= '1';
						if delay_cnt = 1 then
							State <= "0111";
						else
							delay_cnt <= delay_cnt + 1;
						end if;
					when "0111" =>
						delay_cnt <= 0;
						HV_CLK <= '0';
						State <= "0101";
					when "1000" =>
						if empty_cnt = 2 then
							State <= "1011";
						else
							HV_DOUT <= '0';
							empty_cnt <= empty_cnt + 1;
							State <= "1001";
						end if;	
					when "1001" =>
						HV_CLK <= '1';
						if delay_cnt = 1 then
							State <= "1010";
						else
							delay_cnt <= delay_cnt + 1;
						end if;
					when "1010" =>
						HV_CLK <= '0';
						State <= "1000";
					when "1011" =>
						delay_cnt <= 0;
						if index = 0 then
							empty_cnt <= 0;
							State <= "1110";
						else
							index <= index - 1;
							HV_DOUT <= rx_data_buf(index);
							State <= "1100";
						end if;		
					when "1100" =>
						HV_CLK <= '1';
						if delay_cnt = 1 then
							State <= "1101";
						else
							delay_cnt <= delay_cnt + 1;
						end if;
					when "1101" =>
						HV_CLK <= '0';
						State <= "1011";
					when "1110" =>
						if delay_cnt = 4 then 
							State <= "1111";
						else
							delay_cnt <= delay_cnt + 1;
						end if;
					when "1111" =>
						HV_Strobe <= '1';
						HV_BLK <= '0';
						State <= "0000";
				end case;
			end if;
		end process;
end fun;
